/**
 * @file Utility.h
 * @brief 通用功能集合
 * @author BG2EDG (928330305@qq.com)
 * @date 2021-12-18
 *
 * @copyright Copyright (C) 2021, HITCRT_VISION, all rights reserved.
 *
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Author  <th>Description
 * <tr><td>2021-12-18 <td>BG2EDG  <td>
 * </table>
 */
#pragma once

#include <dirent.h>
#include <gtest/gtest.h>
#include <sys/types.h>
#include <unistd.h>

#include <boost/atomic.hpp>
#include <boost/thread.hpp>
#include <chrono>
#include <cmath>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <opencv2/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <typeinfo>

//变量名变字符串
#define VARNAME(x) #x
namespace hitcrt {
// TODO 是否有必要放在一个类里做成静态函数
//算均值
double calcMean(double mean_k_1, double xk, int k);
//算方差时的中间值
double calcS(double s_k_1, double mean_k_1, double mean_k, double xk);  //标准差
double calcStd(double s, int total);
//线性插值(!!!Mat数据类型必须是double!!!）
double lineInterD(const cv::Mat /*double*/ &xs, const cv::Mat /*double*/ &ys, const double &x);
float lineInterF(std::vector<float> xs, std::vector<float> ys, float x);
//输出加前缀
void prefix(std::string file_name, int line, std::string varName);
//格式化时间信息输出 YYYY-MM-DD_HH:MM:SS
std::string formatTime(const time_t time);
std::string formatTime(const std::chrono::system_clock::time_point tp);
//生成随机彩色图片
cv::Mat createRandomImage(const int width, const int height);
//判断文件是否存在
bool isFileExist(const std::string &fileName);

/**
 * @brief 判断val的数值是否在(min,max)范围内
 * @tparam T
 * @param  val              待判断数值
 * @param  min              最小值
 * @param  max              最大值
 * @return true 在
 * @return false 不在
 * @author BG2EDG (928330305@qq.com)
 */
template <typename T>
inline bool isInRange(T val, T min, T max) {
    return val > min && val < max;
}

/**
 * @brief 帧率计算：改自于21步兵FPS类，重写接口和实现，线程安全
 * @author BG2EDG (928330305@qq.com)
 * @attention 此处时间单位均为s
 */
class FPS {
   public:
    FPS(const std::string &name);
    FPS();
    ~FPS() = default;
    // API
    void calc();  //循环中计算帧率,每次到循环中某个点记录一次时间，用于grab和process
    void tic();   //计时开始
    void toc();   //计时结束
    // 控制台输出
    void showFPS() const;
    void showCost() const;
    // set
    void setName(const std::string &name);
    // get
    std::string getName() const;
    double getRealFPS() const;
    double getAvgFPS() const;
    double get5SecFPS() const;
    double getRealCost() const;
    double getAvgCost() const;
    double get5SecCost() const;

   private:
    std::string m_name;                                       //计算对象名称
    bool m_is5SecStart;                                       // 5s计时是否开始
    bool m_isTic;                                             //是否开始过计数
    boost::atomic<double> m_realFPS, m_avgFPS, m_fiveSecFPS;  //帧率
    boost::atomic<double> m_realCost, m_avgCost,
        m_fiveSecCost;                                               //耗时，用于单帧
    uint m_total;                                                    //计数器等变量
    uint m_fiveSecCnt;                                               //最近5s帧率计数器
    std::chrono::_V2::system_clock::time_point m_tic, m_fiveSecTic;  //计时点
};
}  // namespace hitcrt